package com.kingmed.kmss.bpmn.flow.helper;

import java.util.List;
import java.util.Map;

import com.kingmed.kmss.common.utils.DateTimeUtil;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.TaskService;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kingmed.kmss.common.bo.bpmn.AttachmentBO;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class TaskHelper {

	@Autowired
	TaskService taskService;

	@Autowired
	HistoryHelper historyHelper;

	public TaskHelper(TaskService taskService) {
		super();
		this.taskService = taskService;
	}

	public List<Task> findTaskByBizKeyAndUser(String businessKey, String userId) {
		List<Task> tasks = this.taskService.createTaskQuery().processInstanceBusinessKey(businessKey)
				.taskAssigneeLike(userId).list();
		log.info("findTaskByBizKeyAndUser({}) result  is: {}", businessKey, tasks);
		return tasks;
	}

	public Task findTaskById(String taskId) {
		Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
		log.info("findTaskById({}) result  is: {}", taskId, task);
		return task;
	}

	public Task findNextProcessTaskById(String processId, String userId) {
		Task task = this.taskService.createTaskQuery().processInstanceId(processId).taskAssignee(userId).singleResult();
		log.info("findMyNextProcessTaskById({}) result  is: {}", processId, task);
		return task;
	}
	public void test() {
	//	Task task = this.taskService.createTaskQuery().
				
		
	}
	
	public List<Task> findTaskByProcessInstanceId(String processInstanceId) {
		List<Task> resultList = this.taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		log.info("findTaskByProcessInstanceId({}) result is: {}", processInstanceId, resultList);
		return resultList;
	}

	public Task findSingleTaskByExecutionId(String executionId) {
		Task result = this.taskService.createTaskQuery().executionId(executionId).singleResult();
		log.info("findSingleTaskByExecutionId({}) result is: {}", executionId, result);
		return result;
	}

	public List<Task> findTaskByExecutionId(String executionId) {
		List<Task> resultList = this.taskService.createTaskQuery().executionId(executionId).list();
		log.info("findTaskByExecutionId({}) result is: {}", executionId, resultList);
		return resultList;
	}

	public List<Task> findTaskByProcessDefinitionKey(String processDefinitionKey) {

		List<Task> resultList = this.taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).list();
		log.info("findTaskByProcessKey({}) result is: {}", processDefinitionKey, resultList);
		return resultList;
	}

	public List<Task> findTaskByProcessInstanceIdAndGroup(String processInstanceId, String groupName) {
		List<Task> resultList = this.taskService.createTaskQuery().processInstanceId(processInstanceId)
				.taskCandidateGroup(groupName).list();
		log.info("findTaskByProcessInstanceIdAndGroup({},{}) result is: {}", processInstanceId, groupName, resultList);
		return resultList;
	}

	public List<Task> findTaskByGroup(String groupName) {
		List<Task> resultList = this.taskService.createTaskQuery().taskCandidateGroup(groupName).list();
		log.info("findTaskByGroup({}) result is: {}", groupName, resultList);
		return resultList;
	}

	public List<Task> findTaskByProcessDefinitionKeyAndGroup(String processDefinitionKey, String groupName) {

		List<Task> resultList = this.taskService.createTaskQuery().processDefinitionKey(processDefinitionKey)
				.taskCandidateGroup(groupName).list();
		log.info("findTaskByProcessKeyAndGroup({},{}) result is: {}", processDefinitionKey, groupName, resultList);
		return resultList;
	}

	public List<Task> findTaskByProcessInstanceIdAndAssignee(String processInstanceId, String assigneeName) {
		List<Task> resultList = this.taskService.createTaskQuery().processInstanceId(processInstanceId)
				.taskAssignee(assigneeName).list();
		log.info("findTaskByProcessInstanceIdAndAssignee({},{}) result is: {}", processInstanceId, assigneeName,
				resultList);
		return resultList;
	}

	public List<Task> findTaskByProcessDefinitionKeyAndAssignee(String processDefinitionKey, String assigneeName) {
		List<Task> resultList = this.taskService.createTaskQuery().processDefinitionKey(processDefinitionKey)
				.taskAssignee(assigneeName).list();
		log.info("findTaskByProcessKeyAndAssignee({}, {}) result is: {}", processDefinitionKey, assigneeName,
				resultList);
		return resultList;
	}

	public List<Task> findTaskByAssignee(String userId, String assigneeName, String bizType, int firstResult, int maxResult,String startTime, String endTime) {

		TaskQuery query = taskService.createTaskQuery();

		if (StringUtils.isNotEmpty(bizType)) {
			String bizTypeEx = String.format("%%%s%%", bizType);
			query.processInstanceBusinessKeyLike(bizTypeEx);
		} 
		
		if (StringUtils.isNotEmpty(assigneeName)) {
			query = query.or().taskAssigneeLike(assigneeName);
		}
		if (StringUtils.isNotEmpty(userId)) {
			query = query.taskAssignee(userId).endOr();
		}

		if (StringUtils.isNotBlank(endTime)){
			query = query.taskCreatedBefore(DateTimeUtil.stringToDate(endTime));
		}
		if (StringUtils.isNotBlank(startTime)){
			query = query.taskCreatedAfter(DateTimeUtil.stringToDate(startTime));
		}
		query.orderByTaskId().desc();
		List<Task> resultList = query.listPage(firstResult,
				maxResult);
		//List<Task> resultList1 = taskService.createTaskQuery().taskAssignee(assigneeName).list();
		// taskService.createTaskQuery().bu
		// List<Task> resultList =
		// this.taskService.createTaskQuery().taskCandidateOrAssigned(assigneeName).list();
		log.info("findTaskByAssignee({}) result is {}", assigneeName, resultList);
		return resultList;
	}

	@SuppressWarnings("unchecked")
	public <T> T getTaskVariable(String taskId, String varName) {

		return (T) taskService.getVariable(taskId, varName);
	}
	
	public Map<String, Object> getTaskVariables(String taskId) {

		return taskService.getVariables(taskId);
	}
	public List<Task> findTaskByBusinessKey(String businessKey) {

		List<Task> resultList = this.taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
		log.info("findTaskByAssignee({}) result is {}", businessKey, resultList);
		return resultList;
	}

	public List<Task> findTaskByBusinessKeyLike(String businessKeyLike) {

		List<Task> resultList = this.taskService.createTaskQuery().processInstanceBusinessKeyLike(businessKeyLike)
				.list();
		log.info("findTaskByAssignee({}) result is {}", businessKeyLike, resultList);
		return resultList;
	}

	public void claimTask(String taskId, String claimer) {
		this.taskService.claim(taskId, claimer);
	}

	public void assignTask(String taskId, String assignee) {
		this.taskService.setAssignee(taskId, assignee);
	}

	public void addCandidateGroup(String taskId, String groupId) {
		this.taskService.addCandidateGroup(taskId, groupId);
	}

	public void addCandidateUser(String taskId, String userId) {
		this.taskService.addCandidateUser(taskId, userId);
	}

	public Comment addComments(String taskId, String processInstanceId, String type, String message) {

		return this.taskService.addComment(taskId, processInstanceId, type, message);
	}

	public List<Comment> getComments(String taskId) {
		return this.taskService.getTaskComments(taskId);
	}

	public void updateComment(Comment comment) {
		this.taskService.saveComment(comment);
	}

	public Comment findCommentById(String commentId) {
		return this.taskService.getComment(commentId);
	}

	public void unclaimedTask(String taskId) {
		this.taskService.unclaim(taskId);
	}

	public List<IdentityLink> getIdentityLink(String taskId) {
		return this.taskService.getIdentityLinksForTask(taskId);
	}

	public void completeTask(String taskId) {
		this.taskService.complete(taskId);
	}

	public void createAttachment(AttachmentBO attachmentBO) {
		this.taskService.createAttachment(attachmentBO.getType(), attachmentBO.getTaskId(),
				attachmentBO.getProcessInstanceId(), attachmentBO.getName(), attachmentBO.getDescription(),
				attachmentBO.getUrl());

	}

	public void completeTask(String taskId, Map<String, Object> vars) {
		this.taskService.complete(taskId, vars);

	}

	public long countTaskByAssignee(String userId, String assigneeName, String bizType,String startTime, String endTime) {
		TaskQuery query = taskService.createTaskQuery();
		
		if (StringUtils.isNotEmpty(bizType)) {
			//query.taskCategory(bizType);
			String bizTypeEx = String.format("%%%s%%", bizType);
			query.processInstanceBusinessKeyLike(bizTypeEx);
		} 
		
		if (StringUtils.isNotEmpty(assigneeName)) {
			query.or().taskAssigneeLike(assigneeName);
		}
		
		if (StringUtils.isNotEmpty(userId)) {
			query.taskAssignee(userId).endOr();
		}

		if (StringUtils.isNotBlank(endTime)){
			query.taskCreatedBefore(DateTimeUtil.stringToDate(endTime));
		}
		if (StringUtils.isNotBlank(startTime)){
			query.taskCreatedAfter(DateTimeUtil.stringToDate(startTime));
		}

		long count = query.count();
		return count;
	}
}
